package com.gimi.cloud.bbp.manage.controller;

import com.alibaba.fastjson.JSONObject;
import com.gimi.cloud.bbp.common.constant.RedisKeyConstant;
import com.gimi.cloud.bbp.common.enums.ResponseCodeEnum;
import com.gimi.cloud.bbp.common.exception.MsgException;
import com.gimi.cloud.bbp.common.utils.DateUtil;
import com.gimi.cloud.bbp.common.utils.RandomUtil;
import com.gimi.cloud.bbp.common.utils.StringUtil;
import com.gimi.cloud.bbp.common.utils.oss.AliOSSUtil;
import com.gimi.cloud.bbp.common.utils.reqhead.Response;
import com.gimi.cloud.bbp.commonService.mq.enume.QueueEnum;
import com.gimi.cloud.bbp.commonService.mq.service.CommonSenderService;
import com.gimi.cloud.bbp.commonService.redis.RedisService;
import com.gimi.cloud.bbp.dto.base.BaseDTO;
import com.gimi.cloud.bbp.dto.log.LogOperationDTO;
import com.gimi.cloud.bbp.dto.sys.SysResourceDTO;
import com.gimi.cloud.bbp.manage.service.sys.SysResourceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 系统通用功能
 * @author wbj
 * @version 1.0
 * @Description
 * @create 2018-01-26
 **/
@RestController
@RequestMapping("/public")
public class PublicController {
    private static final Logger logger = LoggerFactory.getLogger(PublicController.class);

    private RedisService redisService;
    private SysResourceService sysResourceService;
    private CommonSenderService commonSenderService;

    @Autowired
    public PublicController(RedisService redisService, SysResourceService sysResourceService, CommonSenderService commonSenderService) {
        this.redisService = redisService;
        this.sysResourceService = sysResourceService;
        this.commonSenderService = commonSenderService;
    }

    /**
     * 文件上传接口
     * @param multipartFile
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping("/fileupload")
    public Response fileUpload(HttpServletRequest request, HttpServletResponse response, @RequestParam("file")MultipartFile multipartFile, @RequestParam("type")String type) throws Exception{
        Response resp = new Response();
        InputStream is = multipartFile.getInputStream();
        //获取当前配置的上传路径地址
        JSONObject dirPathConfig =redisService.getJSONObjectConfigByKey(RedisKeyConstant.CONFIG_KEY_PUBLIC_ALIOSS_PATH);
        //判断是否配置有该类型的路径，如果没有，直接返回文件类型错误
        if (null == dirPathConfig || !dirPathConfig.containsKey(type)) {
            throw new MsgException(ResponseCodeEnum.PARAMETER_ERROR,"未获取到配置的文件");
        }
        //获取到当前类型的配置信息
        dirPathConfig = dirPathConfig.getJSONObject(type);
        //获取文件类型
        String[] originalFilenames = multipartFile.getOriginalFilename().split("\\.");
        //新的文件名称
        String fileName =  DateUtil.dateStr3(new Date()) + "" + RandomUtil.getRandomRange(999, 100) +"." + originalFilenames[originalFilenames.length-1];
        //上传文件
        String result = AliOSSUtil.uploadFile(is,dirPathConfig.getString("path"),fileName);
        Map<String,String> data = new HashMap<>(10);
        //获取当前类型配置的有效时间
        String url = AliOSSUtil.getFileUrl(result,dirPathConfig.getLong("second"));
        data.put("url",url);
        data.put("shortUrl",result);
        data.put("extra",request.getParameter("extra"));
        SysResourceDTO sysResourceDTO = new SysResourceDTO();
        sysResourceDTO.setReFileType(originalFilenames[originalFilenames.length-1]);
        sysResourceDTO.setReType(type);
        sysResourceDTO.setReTypeName(dirPathConfig.getString("typeName"));
        sysResourceDTO.setReName(multipartFile.getOriginalFilename());
        sysResourceDTO.setReOssUrl(result);
        sysResourceDTO.setReUrl(url);
        sysResourceService.saveOrUpdate(sysResourceDTO);
        resp.setRes_data(data);
        resp.setResponseCode(ResponseCodeEnum.SUCCESSED);
        return resp;
    }

    /**
     * 获取图形验证码
     * @param request
     * @param response
     * @param dto
     * @throws Exception
     */
    @PostMapping("/validiateCode")
    public Response validiatecode(HttpServletRequest request, HttpServletResponse response, @RequestBody BaseDTO dto) throws Exception{
        logger.info("开始获取验证码");
        // 定义图片的width
        int width = 120;
        // 定义图片的height
        int height = 30;
        // 定义图片上显示验证码的个数
        int codeCount = 5;
        //水平字体间的间距
        int spacing = 15;
        //字体大小
        int fontHeight = 22;
        //纵向padding
        int codeY = 20;
        char[] codeSequence = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
                'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
        //验证码过期时间
        Long validateTime = 60L;
        JSONObject validateCodeRule = redisService.getJSONObjectConfigByKey(RedisKeyConstant.CONFIG_KEY_MANAGE_VALIDATE_CODE_RULE);
        if(null != validateCodeRule){
            //验证码宽度
            width = validateCodeRule.getInteger("width") != null?validateCodeRule.getInteger("width"):width;
            //验证码高度
            height = validateCodeRule.getInteger("height") != null?validateCodeRule.getInteger("height"):height;
            //验证字符个数
            codeCount = validateCodeRule.getInteger("codeCount") != null?validateCodeRule.getInteger("codeCount"):codeCount;
            //水平字体间的间距
            spacing = validateCodeRule.getInteger("spacing") != null?validateCodeRule.getInteger("spacing"):spacing;
            //字体大小
            fontHeight = validateCodeRule.getInteger("fontHeight") != null?validateCodeRule.getInteger("fontHeight"):fontHeight;
            //纵向padding
            codeY = validateCodeRule.getInteger("codeY") != null?validateCodeRule.getInteger("codeY"):codeY;
            codeSequence = StringUtil.isNotBlank(validateCodeRule.getString("codeSequence"))?validateCodeRule.getString("codeSequence").toCharArray():codeSequence;
            //验证码过期时间
            validateTime = validateCodeRule.getLong("validateTime")!=null?validateCodeRule.getLong("validateTime"):validateTime;
        }
        // 定义图像buffer
        BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics gd = buffImg.getGraphics();
        // 创建一个随机数生成器类
        Random random = new Random();
        gd.setColor(Color.WHITE);
        gd.fillRect(0, 0, width, height);
        // 创建字体，字体的大小应该根据图片的高度来定。
        Font font = new Font("Fixedsys", Font.BOLD, fontHeight);
        // 设置字体。
        gd.setFont(font);
        // 画边框。
        gd.setColor(Color.BLACK);
        gd.drawRect(0, 0, width - 1, height - 1);
        gd.setColor(Color.BLACK);
        // 随机产生40条干扰线，使图象中的认证码不易被其它程序探测到。
        for (int i = 0; i < 40; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int xl = random.nextInt(12);
            int yl = random.nextInt(12);
            gd.drawLine(x, y, x + xl, y + yl);
        }
        // 随机产生40条干扰线，使图象中的认证码不易被其它程序探测到。
        StringBuffer randomCode = new StringBuffer();
        int red = 0, green = 0, blue = 0;
        //开始生成验证码
        for (int i = 0; i < codeCount; i++) {
            // 随机产生40条干扰线，使图象中的认证码不易被其它程序探测到。
            String code = String.valueOf(codeSequence[random.nextInt(codeSequence.length)]);
            red = random.nextInt(255);
            green = random.nextInt(255);
            blue = random.nextInt(255);
            gd.setColor(new Color(red, green, blue));
            gd.drawString(code, (i + 1) * spacing, codeY);
            randomCode.append(code);
        }
        // 创建编码对象
        Base64.Encoder base64 = Base64.getEncoder();
        // 创建字符流
        ByteArrayOutputStream bs = new ByteArrayOutputStream();
        // 写入字符流
        ImageIO.write(buffImg, "jpeg", bs);
        // 转码成字符串
        String imgsrc = base64.encodeToString(bs.toByteArray());
        bs.close();
        Map<String,Object> resData = new HashMap<>();
        String validateKey = UUID.randomUUID().toString().replace("-","");
        resData.put("validateCode",imgsrc);
        resData.put("validateKey", validateKey);
        redisService.set(RedisKeyConstant.PUBLIC_VALIDATE_CODE_PREFIX +validateKey,randomCode.toString(),validateTime, TimeUnit.SECONDS);
        Response resp = new Response();
        resp.setResponseCode(ResponseCodeEnum.SUCCESSED,"获取成功");
        resp.setRes_data(resData);
        return resp;
    }

    /**
     * 根据文件名称获取AliOss路径
     * @param request
     * @param response
     * @param fileName 文件名称
     * @throws Exception
     */
    @RequestMapping("/getFilePath")
    public Response getFilePath(HttpServletRequest request,HttpServletResponse response,@RequestParam("fileName")String fileName) throws Exception{
        //涉及缓存，默认超时时间为一年
        String url = AliOSSUtil.getFileUrl(fileName,60 * 60 * 24 * 365);
        Response resp = new Response();
        resp.setResponseCode(ResponseCodeEnum.SUCCESSED);
        resp.setRes_data(url);
        return resp;
    }

    /**
     * 推送操作日志到MQ
     * @param request
     * @param response
     * @param dto
     * @return
     * @throws Exception
     */
    @RequestMapping("/sendOperationLogToMq")
    public Response sendOperationLogToMq(HttpServletRequest request, HttpServletResponse response, @RequestBody LogOperationDTO dto) throws  Exception{
        commonSenderService.sendMessage2Rabbitmq(QueueEnum.OPERATION_LOG,dto);
        Response resp = new Response();
        resp.setResponseCode(ResponseCodeEnum.SUCCESSED);
        return resp;
    }
}
